home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / lang / sbasic02 / sbasic.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-04  |  8.1 KB  |  544 lines

  1. /**********************************************************/
  2. /* SMALL BASIC Interpeter (sbasic.c) V0.2                 */
  3. /* Copyright (C) 1994 James J. Bielman                    */
  4. /* Adapted from _C Power User's Guide_ by Herbert Schildt */
  5. /**********************************************************/
  6.  
  7. #include<stdio.h>
  8. #include<setjmp.h>
  9. #include<math.h>
  10. #include<ctype.h>
  11. #include<stdlib.h>
  12.  
  13. #define NUM_LAB         100
  14. #define LAB_LEN         10
  15. #define FOR_NEST        25
  16. #define SUB_NEST        25
  17. #define PROG_SIZE       0xFFFF
  18.  
  19. #define DELIMITER       1
  20. #define VARIABLE        2
  21. #define NUMBER          3
  22. #define COMMAND         4
  23. #define STRING          5
  24. #define QUOTE           6
  25.  
  26. #define PRINT           1
  27. #define INPUT           2
  28. #define IF              3
  29. #define THEN            4
  30. #define FOR             5
  31. #define NEXT            6
  32. #define TO              7
  33. #define GOTO            8
  34. #define EOL             9
  35. #define FINISHED        10
  36. #define GOSUB           11
  37. #define RETURN          12
  38. #define END             13
  39. #define ELSE        14
  40.  
  41. char    *prog;          /* holds expression to be analyzed */
  42. jmp_buf e_buf;          /* holds env for longjmp() */
  43. int     source_line = 1;
  44.  
  45. int variables[26] = { 0, 0, 0, 0, 0, 0, 0, 0,
  46.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  47.         0, 0, 0, 0, 0, 0, 0, 0 
  48. };
  49.  
  50. struct commands {       /* keyword lookup table */
  51.     char command[20];
  52.     char tok;
  53. } table[] = {
  54.     "print",  PRINT,
  55.     "input",  INPUT,
  56.     "if",     IF,
  57.     "then",   THEN,
  58.     "else",   ELSE,
  59.     "goto",   GOTO,
  60.     "for",    FOR,
  61.     "next",   NEXT,
  62.     "to",     TO,
  63.     "gosub",  GOSUB,
  64.     "return", RETURN,
  65.     "end",    END,
  66.     "",       END,
  67. };
  68.  
  69. char token[80];
  70. char token_type, tok;
  71.  
  72. struct label {
  73.     char name[LAB_LEN];
  74.     char *p;
  75. };
  76. struct label label_table[NUM_LAB];
  77.  
  78. struct for_stack {
  79.     int var;
  80.     int target;
  81.     char *loc;
  82. } fstack[FOR_NEST];
  83.  
  84. char *gstack[SUB_NEST];
  85.  
  86. int ftos;               /* index to top of FOR stack */
  87. int gtos;               /* index to top of GOTO stack */
  88.  
  89. int main(int argc, char **argv)
  90. {
  91.     char in[80];
  92.     int answer;
  93.     char *p_buf;
  94.     char *t;
  95.  
  96.     if(argc < 2)
  97.     {
  98.         printf("usage: %s filename ..\n", argv[0]);
  99.         exit(1);
  100.     }
  101.  
  102.     printf("Small BASIC V0.2\n");
  103.     printf("Copyright (C) 1994 James J. Bielman\n");
  104.     printf("All Rights Reserved\n");
  105.     printf("\nThis is free software, with ABSOLUTELY NO WARANTEE\n");
  106.     printf("Read the file GNU.LIC for details\n\n");
  107.  
  108.     /* Allocating memory for the program */
  109.     if(!(p_buf = (char *)malloc(PROG_SIZE)))
  110.     {
  111.         printf("memory allocation error. .\n");
  112.         exit(1);
  113.     }
  114.  
  115.     /* Load the program */
  116.     if(!load_program(p_buf, argv[1])) exit(2);
  117.  
  118.     if(setjmp(e_buf)) exit(1);
  119.  
  120.     prog = p_buf;
  121.     scan_labels();
  122.     ftos = 0;
  123.     gtos = 0;
  124.     do
  125.     {
  126.         token_type = get_token();
  127.  
  128.         exec_command();
  129.     } while(1);
  130. }
  131.  
  132. /* Modified 4.11.94 JJB */
  133. exec_command()
  134. {
  135.     if(token_type == VARIABLE)
  136.     {
  137.         putback();
  138.         assignment();
  139.     }
  140.     else
  141.         switch(tok)
  142.         {
  143.             case PRINT:
  144.                 print();
  145.                 break;
  146.  
  147.             case GOTO:
  148.                 exec_goto();
  149.                 break;
  150.  
  151.             case IF:
  152.                 exec_if();
  153.                 break;
  154.  
  155.             case FOR:
  156.                 exec_for();
  157.                 break;
  158.  
  159.             case NEXT:
  160.                 next();
  161.                 break;
  162.  
  163.             case INPUT:
  164.                 input();
  165.                 break;
  166.  
  167.             case GOSUB:
  168.                 gosub();
  169.                 break;
  170.  
  171.             case RETURN:
  172.                 greturn();
  173.                 break;
  174.  
  175.             case END:
  176.             case FINISHED:
  177.                 exit(0);
  178.                 break;
  179.         }
  180. }
  181.  
  182. int load_program(char *p, char *fname)
  183. {
  184.     FILE *fp;
  185.     int i = 0;
  186.  
  187.     if(!(fp = fopen(fname, "r"))) return 0;
  188.  
  189.     i = 0;
  190.     do
  191.     {
  192.         *p = getc(fp);
  193.         p++; i++;
  194.  
  195.     } while(!feof(fp) && i < PROG_SIZE);
  196.     fclose(fp);
  197.     return 1;
  198. }
  199.  
  200. int assignment()
  201. {
  202.     int var, value;
  203.  
  204.     /* Get the variable name */
  205.     get_token();
  206.     if(!isalpha(*token))
  207.     {
  208.         serror(4);
  209.         return;
  210.     }
  211.  
  212.     var = toupper(*token) - 'A';
  213.  
  214.     /* get the = */
  215.     get_token();
  216.     if(*token != '=')
  217.     {
  218.         serror(3);
  219.         return;
  220.     }
  221.  
  222.     /* get the value */
  223.     get_exp(&value);
  224.  
  225.     /* assign the var */
  226.     variables[var] = value;
  227. }
  228.  
  229. int print()
  230. {
  231.     int answer;
  232.     int len=0, spaces;
  233.     char last_delim;
  234.  
  235.     do
  236.     {
  237.         get_token();    /* get next list item */
  238.  
  239.         if(token_type == QUOTE)  /* is string */
  240.         {
  241.             printf(token);
  242.             len += strlen(token);
  243.             get_token();
  244.         }
  245.         else /* is expression */
  246.         {
  247.             putback();
  248.             get_exp(&answer);
  249.             get_token();
  250.             len += printf("%d", answer);
  251.         } 
  252.  
  253.         last_delim = *token;
  254.  
  255.         if(*token == ',')
  256.         {
  257.             spaces = 8 - (len % 8);
  258.             len += spaces;
  259.             while(spaces)
  260.             {
  261.                 printf(" ");
  262.                 spaces--;
  263.             }
  264.         }
  265.         else if(*token == ';') /* nothin */ ;
  266.         else break;
  267.  
  268.     } while(*token == ';' || *token == ',');
  269.  
  270.     if(last_delim != ';' && last_delim != ',') printf("\n");
  271. }
  272.  
  273. int scan_labels()
  274. {
  275.     int addr;
  276.     char *temp;
  277.  
  278.     label_init();
  279.     temp = prog;
  280.  
  281.     get_token();
  282.     if(token_type ==  NUMBER)
  283.     {
  284.         strcpy(label_table[0].name, token);
  285.         label_table[0].p = prog;
  286.     }
  287.  
  288.     find_eol();
  289.     do
  290.     {
  291.         get_token();
  292.         if(token_type == NUMBER)
  293.         {
  294.             addr = get_next_label(token);
  295.             if(addr == -1 || addr == -2)
  296.                  (addr == -1) ? serror(5) : serror(6);
  297.  
  298.             strcpy(label_table[addr].name, token);
  299.             label_table[addr].p = prog;
  300.         }
  301.         if(tok != EOL) find_eol();
  302.     } while(tok != FINISHED);
  303.     prog = temp;
  304. }
  305.  
  306. int find_eol()
  307. {
  308.     while(*prog != '\n' && *prog != '\0') ++prog;
  309. /*    if(*prog) prog++;  */
  310. }
  311.  
  312. int get_next_label(char *s)
  313. {
  314.     register int t;
  315.  
  316.     for(t = 0; t < NUM_LAB; ++t)
  317.     {
  318.         if(label_table[t].name[0] == 0) return t;
  319.         if(!strcmp(label_table[t].name, s)) return -2;
  320.     }
  321.  
  322.     return -1;
  323. }
  324.  
  325. char *find_label(char *s)
  326. {
  327.     register t;
  328.  
  329.     for(t = 0; t < NUM_LAB; ++t)
  330.         if(!strcmp(label_table[t].name, s)) return label_table[t].p;
  331.     return '\0';
  332. }
  333.  
  334. int exec_goto()
  335. {
  336.     char *loc;
  337.  
  338.     get_token();
  339.  
  340.     loc = find_label(token);
  341.     if(loc == '\0') serror(7);
  342.     else prog = loc;
  343. }
  344.  
  345. int label_init()
  346. {
  347.     register t;
  348.  
  349.     for(t = 0; t < NUM_LAB; ++t) label_table[t].name[0] = '\0';
  350. }
  351.  
  352. int exec_if()
  353. {
  354.     int x, y, cond;
  355.     char op;
  356.  
  357.     get_exp(&x);
  358.  
  359.     get_token();
  360.     if(!strchr("=<>", *token))
  361.     {
  362.         serror(0);
  363.         return;
  364.     }
  365.     op = *token;
  366.  
  367.     get_exp(&y);
  368.  
  369.     cond = 0;
  370.     switch(op)
  371.     {
  372.         case '<':
  373.             if(x < y) cond = 1;
  374.             break;
  375.  
  376.         case '>':
  377.             if(x > y) cond = 1;
  378.             break;
  379.  
  380.         case '=':
  381.             if(x == y) cond = 1;
  382.             break;
  383.     }
  384.  
  385.     get_token();
  386.  
  387.     /* Check for THEN statement */
  388.     if(tok != THEN)
  389.     {
  390.         serror(8);
  391.         return;
  392.     }
  393.  
  394.     if(cond)
  395.     {
  396.         /* Execute until ELSE or end-of-line */
  397.         do
  398.         {
  399.             get_token();
  400.             exec_command();
  401.         } while(tok != ELSE && tok != EOL && tok != FINISHED);
  402.  
  403.         if(tok == ELSE) find_eol();
  404.     }
  405.     else
  406.     {
  407.         /* Skip ahead until ELSE */
  408.         while(tok != ELSE && tok != EOL)
  409.             get_token();
  410.     }
  411. }
  412.  
  413. void fpush(struct for_stack i)
  414. {
  415.     if(ftos > FOR_NEST)
  416.         serror(10);
  417.  
  418.     fstack[ftos] = i;
  419.     ftos++;
  420. }
  421.  
  422. struct for_stack fpop()
  423. {
  424.     ftos--;
  425.     if(ftos < 0) serror(11);
  426.     return(fstack[ftos]);
  427. }
  428.  
  429. int exec_for()
  430. {
  431.     struct for_stack i;
  432.     int value;
  433.  
  434.     get_token(); /* get control var */
  435.     if(!isalpha(*token))
  436.     {
  437.         serror(4);
  438.         return;
  439.     }
  440.  
  441.     i.var = toupper(*token) - 'A';
  442.  
  443.     get_token();
  444.     if(*token != '=')
  445.     {
  446.         serror(3);
  447.         return;
  448.     }
  449.  
  450.     get_exp(&value);
  451.  
  452.     variables[i.var] = value;
  453.  
  454.     get_token();
  455.  
  456.     if(tok != TO) serror(9);
  457.     get_exp(&i.target);
  458.  
  459.     if(value >= variables[i.var])
  460.     {
  461.         i.loc = prog;
  462.         fpush(i);
  463.     }
  464.     else
  465.         while(tok != NEXT) get_token();
  466. }
  467.  
  468. int next()
  469. {
  470.     struct for_stack i;
  471.  
  472.     i = fpop();
  473.  
  474.     variables[i.var]++;
  475.     if(variables[i.var] > i.target) return;
  476.     fpush(i);
  477.     prog = i.loc;
  478. }
  479.  
  480. int input()
  481. {
  482.     char str[80], var;
  483.     int i;
  484.  
  485.     get_token();
  486.     if(token_type == QUOTE)
  487.     {
  488.         printf(token);
  489.         get_token();
  490.         if(*token != ',' && *token != ';') serror(1);
  491.         get_token();
  492.     }
  493.     else printf("? ");
  494.     var = toupper(*token) - 'A';
  495.  
  496.     scanf("%d", &i);
  497.  
  498.     variables[var] = i;
  499. }
  500.  
  501. int gpush(char *s)
  502. {
  503.     gtos++;
  504.  
  505.     if(gtos == SUB_NEST)
  506.     {
  507.         serror(12);
  508.         return;
  509.     }
  510.  
  511.     gstack[gtos] = s;
  512. }
  513.  
  514. char *gpop()
  515. {
  516.     if(gtos == 0)
  517.     {
  518.         serror(13);
  519.         return 0;
  520.     }
  521.     return(gstack[gtos--]);
  522. }
  523.  
  524. int gosub()
  525. {
  526.     char *loc;
  527.  
  528.     get_token();
  529.  
  530.     loc = find_label(token);
  531.     if(loc == '\0')
  532.         serror(7);
  533.     else
  534.     {
  535.         gpush(prog);
  536.         prog = loc;
  537.     }
  538. }
  539.  
  540. int greturn()
  541. {
  542.     prog = gpop();
  543. }
  544.